From 47fd548a71332ad253a8ddbf3b0b2f7975714647 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Tue, 2 Sep 2025 13:20:13 +0200 Subject: [PATCH] mwan3: common.sh: fix src_ip detection for ipv6-PD IPv6 via PPPoE often receives a prefix, not an address. In that case mwan3_get_src_ip would not find an address and fall back to ::. However in case of multiple IPv6 upstreams, this no longer means a ping (such as done by uptime check) succeeds, for there are multiple addresses. With this, mwan3 can effectively load-balance/fail-over on a PPPoE IPv6 prefix and a secondary (LTE) acquired /64 without immediately disabling the IPv6 prefix interface as soon as the secondary IPv6 interface comes up. I think this change is also a fix to #26690 but I'm not 100% sure of that. Signed-off-by: Fabian Groffen --- net/mwan3/files/lib/mwan3/common.sh | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/net/mwan3/files/lib/mwan3/common.sh b/net/mwan3/files/lib/mwan3/common.sh index 8b4adbdf08..df42a0a2c9 100644 --- a/net/mwan3/files/lib/mwan3/common.sh +++ b/net/mwan3/files/lib/mwan3/common.sh @@ -74,8 +74,33 @@ mwan3_get_src_ip() $addr_cmd _src_ip "$true_iface" if [ -z "$_src_ip" ]; then - network_get_device device $true_iface - _src_ip=$($IP address ls dev $device 2>/dev/null | sed -ne "$sed_str") + if [ "$family" = "ipv6" ]; then + # on IPv6-PD interfaces (like PPPoE interfaces) we don't + # have a real address, just a prefix, that can be delegated + # to interfaces, because using :: (the fallback above) or + # the local address (fe80:... which will be returned from + # the sed_str expression defined above) will not work + # (reliably, if at all) try to find an address which we can + # use instead + network_get_prefix6 _src_ip "$true_iface" + if [ -n "$_src_ip" ]; then + # got a prefix like 2001:xxxx:yyyy::/48, clean it up to + # only contain the prefix -> 2001:xxxx:yyyy + _src_ip=$(echo "$_src_ip" | sed -e 's;:*/.*$;;') + # find an interface with a delegated address, and use + # it, this would be sth like 2001:xxxx:yyyy:zzzz:... + # we just select the first address that matches the prefix + # NOTE: is there a better/more reliable way to get a + # usable address to use as source for pings here? + local pfx_sed + pfx_sed='s/ *inet6 \('"$_src_ip"':[0-6a-f:]\+\).* scope.*/\1/' + _src_ip=$($IP address ls | sed -ne "${pfx_sed};T;p;q") + fi + fi + if [ -z "$_src_ip" ]; then + network_get_device device $true_iface + _src_ip=$($IP address ls dev $device 2>/dev/null | sed -ne "$sed_str") + fi if [ -n "$_src_ip" ]; then LOG warn "no src $family address found from netifd for interface '$true_iface' dev '$device' guessing $_src_ip" else -- 2.30.2